home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gsptype1.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  24.9 KB  |  820 lines

  1. /* Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gsptype1.c,v 1.2 2000/09/19 19:00:31 lpd Exp $ */
  20. /* PatternType 1 pattern implementation */
  21. #include "math_.h"
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gsrop.h"
  25. #include "gsstruct.h"
  26. #include "gsutil.h"        /* for gs_next_ids */
  27. #include "gxarith.h"
  28. #include "gxfixed.h"
  29. #include "gxmatrix.h"
  30. #include "gxcoord.h"        /* for gs_concat, gx_tr'_to_fixed */
  31. #include "gxcspace.h"        /* for gscolor2.h */
  32. #include "gxcolor2.h"
  33. #include "gxdcolor.h"
  34. #include "gxdevice.h"
  35. #include "gxdevmem.h"
  36. #include "gxclip2.h"
  37. #include "gspath.h"
  38. #include "gxpath.h"
  39. #include "gxpcolor.h"
  40. #include "gxp1impl.h"        /* requires gxpcolor.h */
  41. #include "gzstate.h"
  42. #include "gsimage.h"
  43. #include "gsiparm4.h"
  44.  
  45. /* GC descriptors */
  46. private_st_pattern1_template();
  47. private_st_pattern1_instance();
  48.  
  49. /* GC procedures */
  50. private ENUM_PTRS_BEGIN(pattern1_instance_enum_ptrs) {
  51.     if (index < st_pattern1_template_max_ptrs) {
  52.     gs_ptr_type_t ptype =
  53.         ENUM_SUPER_ELT(gs_pattern1_instance_t, st_pattern1_template,
  54.                template, 0);
  55.  
  56.     if (ptype)
  57.         return ptype;
  58.     return ENUM_OBJ(NULL);    /* don't stop early */
  59.     }
  60.     ENUM_PREFIX(st_pattern_instance, st_pattern1_template_max_ptrs);
  61. } ENUM_PTRS_END
  62. private RELOC_PTRS_BEGIN(pattern1_instance_reloc_ptrs) {
  63.     RELOC_PREFIX(st_pattern_instance);
  64.     RELOC_SUPER(gs_pattern1_instance_t, st_pattern1_template, template);
  65. } RELOC_PTRS_END
  66.  
  67. /* Define a PatternType 1 pattern. */
  68. private pattern_proc_uses_base_space(gs_pattern1_uses_base_space);
  69. private pattern_proc_make_pattern(gs_pattern1_make_pattern);
  70. private pattern_proc_get_pattern(gs_pattern1_get_pattern);
  71. private const gs_pattern_type_t gs_pattern1_type = {
  72.     1, {
  73.     gs_pattern1_uses_base_space, gs_pattern1_make_pattern,
  74.     gs_pattern1_get_pattern, gs_pattern1_remap_color
  75.     }
  76. };
  77.  
  78. /*
  79.  * Build a PatternType 1 Pattern color space.
  80.  */
  81. int
  82. gs_cspace_build_Pattern1(gs_color_space ** ppcspace,
  83.             const gs_color_space * pbase_cspace, gs_memory_t * pmem)
  84. {
  85.     gs_color_space *pcspace = 0;
  86.     int code;
  87.  
  88.     if (pbase_cspace != 0) {
  89.     if (gs_color_space_num_components(pcspace) < 0)        /* Pattern space */
  90.         return_error(gs_error_rangecheck);
  91.     }
  92.     code = gs_cspace_alloc(&pcspace, &gs_color_space_type_Pattern, pmem);
  93.     if (code < 0)
  94.     return code;
  95.     if (pbase_cspace != 0) {
  96.     pcspace->params.pattern.has_base_space = true;
  97.     gs_cspace_init_from((gs_color_space *) & (pcspace->params.pattern.base_space),
  98.                 pbase_cspace
  99.         );
  100.     } else
  101.     pcspace->params.pattern.has_base_space = false;
  102.     *ppcspace = pcspace;
  103.     return 0;
  104. }
  105.  
  106. /* Initialize a PatternType 1 pattern template. */
  107. void
  108. gs_pattern1_init(gs_pattern1_template_t * ppat)
  109. {
  110.     gs_pattern_common_init((gs_pattern_template_t *)ppat, &gs_pattern1_type);
  111. }
  112.  
  113. /* Make an instance of a PatternType 1 pattern. */
  114. private int compute_inst_matrix(P3(gs_pattern1_instance_t * pinst,
  115.                    const gs_state * saved, gs_rect * pbbox));
  116. int
  117. gs_makepattern(gs_client_color * pcc, const gs_pattern1_template_t * pcp,
  118.            const gs_matrix * pmat, gs_state * pgs, gs_memory_t * mem)
  119. {
  120.     return gs_pattern1_make_pattern(pcc, (const gs_pattern_template_t *)pcp,
  121.                     pmat, pgs, mem);
  122. }
  123. private int
  124. gs_pattern1_make_pattern(gs_client_color * pcc,
  125.              const gs_pattern_template_t * ptemp,
  126.              const gs_matrix * pmat, gs_state * pgs,
  127.              gs_memory_t * mem)
  128. {
  129.     const gs_pattern1_template_t *pcp = (const gs_pattern1_template_t *)ptemp;
  130.     gs_pattern1_instance_t inst;
  131.     gs_pattern1_instance_t *pinst;
  132.     gs_state *saved;
  133.     gs_rect bbox;
  134.     gs_fixed_rect cbox;
  135.     int code = gs_make_pattern_common(pcc, (const gs_pattern_template_t *)pcp,
  136.                       pmat, pgs, mem,
  137.                       &st_pattern1_instance);
  138.  
  139.     if (code < 0)
  140.     return code;
  141.     if (mem == 0)
  142.     mem = gs_state_memory(pgs);
  143.     pinst = (gs_pattern1_instance_t *)pcc->pattern;
  144.     *(gs_pattern_instance_t *)&inst = *(gs_pattern_instance_t *)pinst;
  145.     saved = inst.saved;
  146.     switch (pcp->PaintType) {
  147.     case 1:        /* colored */
  148.         gs_set_logical_op(saved, lop_default);
  149.         break;
  150.     case 2:        /* uncolored */
  151.         gx_set_device_color_1(saved);
  152.         break;
  153.     default:
  154.         code = gs_note_error(gs_error_rangecheck);
  155.         goto fsaved;
  156.     }
  157.     inst.template = *pcp;
  158.     code = compute_inst_matrix(&inst, saved, &bbox);
  159.     if (code < 0)
  160.     goto fsaved;
  161. #define mat inst.step_matrix
  162.     if_debug6('t', "[t]step_matrix=[%g %g %g %g %g %g]\n",
  163.           mat.xx, mat.xy, mat.yx, mat.yy, mat.tx, mat.ty);
  164.     if_debug4('t', "[t]bbox=(%g,%g),(%g,%g)\n",
  165.           bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
  166.     {
  167.     float bbw = bbox.q.x - bbox.p.x;
  168.     float bbh = bbox.q.y - bbox.p.y;
  169.  
  170.     /* If the step and the size agree to within 1/2 pixel, */
  171.     /* make them the same. */
  172.     inst.size.x = (int)(bbw + 0.8);        /* 0.8 is arbitrary */
  173.     inst.size.y = (int)(bbh + 0.8);
  174.  
  175.     if (inst.size.x == 0 || inst.size.y == 0) {
  176.         /*
  177.          * The pattern is empty: the stepping matrix doesn't matter.
  178.          */
  179.         gs_make_identity(&mat);
  180.         bbox.p.x = bbox.p.y = bbox.q.x = bbox.q.y = 0;
  181.     } else {
  182.         /* Check for singular stepping matrix. */
  183.         if (fabs(mat.xx * mat.yy - mat.xy * mat.yx) < 1.0e-6) {
  184.         code = gs_note_error(gs_error_rangecheck);
  185.         goto fsaved;
  186.         }
  187.         if (mat.xy == 0 && mat.yx == 0 &&
  188.         fabs(fabs(mat.xx) - bbw) < 0.5 &&
  189.         fabs(fabs(mat.yy) - bbh) < 0.5
  190.         ) {
  191.         gs_scale(saved, fabs(inst.size.x / mat.xx),
  192.              fabs(inst.size.y / mat.yy));
  193.         code = compute_inst_matrix(&inst, saved, &bbox);
  194.         if (code < 0)
  195.             goto fsaved;
  196.         if_debug2('t',
  197.               "[t]adjusted XStep & YStep to size=(%d,%d)\n",
  198.               inst.size.x, inst.size.y);
  199.         if_debug4('t', "[t]bbox=(%g,%g),(%g,%g)\n",
  200.               bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
  201.         }
  202.     }
  203.     }
  204.     if ((code = gs_bbox_transform_inverse(&bbox, &mat, &inst.bbox)) < 0)
  205.     goto fsaved;
  206.     if_debug4('t', "[t]ibbox=(%g,%g),(%g,%g)\n",
  207.           inst.bbox.p.x, inst.bbox.p.y, inst.bbox.q.x, inst.bbox.q.y);
  208.     inst.is_simple = (fabs(mat.xx) == inst.size.x && mat.xy == 0 &&
  209.               mat.yx == 0 && fabs(mat.yy) == inst.size.y);
  210.     if_debug6('t',
  211.           "[t]is_simple? xstep=(%g,%g) ystep=(%g,%g) size=(%d,%d)\n",
  212.           inst.step_matrix.xx, inst.step_matrix.xy,
  213.           inst.step_matrix.yx, inst.step_matrix.yy,
  214.           inst.size.x, inst.size.y);
  215.     /* Absent other information, instances always require a mask. */
  216.     inst.uses_mask = true;
  217.     gx_translate_to_fixed(saved, float2fixed(mat.tx - bbox.p.x),
  218.               float2fixed(mat.ty - bbox.p.y));
  219.     mat.tx = bbox.p.x;
  220.     mat.ty = bbox.p.y;
  221. #undef mat
  222.     cbox.p.x = fixed_0;
  223.     cbox.p.y = fixed_0;
  224.     cbox.q.x = int2fixed(inst.size.x);
  225.     cbox.q.y = int2fixed(inst.size.y);
  226.     code = gx_clip_to_rectangle(saved, &cbox);
  227.     if (code < 0)
  228.     goto fsaved;
  229.     inst.id = gs_next_ids(1);
  230.     *pinst = inst;
  231.     return 0;
  232. #undef mat
  233.   fsaved:gs_state_free(saved);
  234.     gs_free_object(mem, pinst, "gs_makepattern");
  235.     return code;
  236. }
  237. /* Compute the stepping matrix and device space instance bounding box */
  238. /* from the step values and the saved matrix. */
  239. private int
  240. compute_inst_matrix(gs_pattern1_instance_t * pinst, const gs_state * saved,
  241.             gs_rect * pbbox)
  242. {
  243.     double xx = pinst->template.XStep * saved->ctm.xx;
  244.     double xy = pinst->template.XStep * saved->ctm.xy;
  245.     double yx = pinst->template.YStep * saved->ctm.yx;
  246.     double yy = pinst->template.YStep * saved->ctm.yy;
  247.  
  248.     /* Adjust the stepping matrix so all coefficients are >= 0. */
  249.     if (xx == 0 || yy == 0) {    /* We know that both xy and yx are non-zero. */
  250.     double temp;
  251.  
  252.     temp = xx, xx = yx, yx = temp;
  253.     temp = xy, xy = yy, yy = temp;
  254.     }
  255.     if (xx < 0)
  256.     xx = -xx, xy = -xy;
  257.     if (yy < 0)
  258.     yx = -yx, yy = -yy;
  259.     /* Now xx > 0, yy > 0. */
  260.     pinst->step_matrix.xx = xx;
  261.     pinst->step_matrix.xy = xy;
  262.     pinst->step_matrix.yx = yx;
  263.     pinst->step_matrix.yy = yy;
  264.     pinst->step_matrix.tx = saved->ctm.tx;
  265.     pinst->step_matrix.ty = saved->ctm.ty;
  266.     return gs_bbox_transform(&pinst->template.BBox, &ctm_only(saved),
  267.                  pbbox);
  268. }
  269.  
  270. /* Test whether a PatternType 1 pattern uses a base space. */
  271. private bool
  272. gs_pattern1_uses_base_space(const gs_pattern_template_t *ptemp)
  273. {
  274.     return ((const gs_pattern1_template_t *)ptemp)->PaintType == 2;
  275. }
  276.  
  277. /* getpattern for PatternType 1 */
  278. /* This is only intended for the benefit of pattern PaintProcs. */
  279. private const gs_pattern_template_t *
  280. gs_pattern1_get_pattern(const gs_pattern_instance_t *pinst)
  281. {
  282.     return (const gs_pattern_template_t *)
  283.     &((const gs_pattern1_instance_t *)pinst)->template;
  284. }
  285. const gs_pattern1_template_t *
  286. gs_getpattern(const gs_client_color * pcc)
  287. {
  288.     const gs_pattern_instance_t *pinst = pcc->pattern;
  289.  
  290.     return (pinst == 0 || pinst->type != &gs_pattern1_type ? 0 :
  291.         &((const gs_pattern1_instance_t *)pinst)->template);
  292. }
  293.  
  294. /*
  295.  *  Code for generating patterns from bitmaps and pixmaps.
  296.  */
  297.  
  298. /*
  299.  *  The following structures are realized here only because this is the
  300.  *  first location in which they were needed. Otherwise, there is nothing
  301.  *  about them that is specific to patterns.
  302.  */
  303. public_st_gs_bitmap();
  304. public_st_gs_tile_bitmap();
  305. public_st_gs_depth_bitmap();
  306. public_st_gs_tile_depth_bitmap();
  307. public_st_gx_strip_bitmap();
  308.  
  309. /*
  310.  *  Structure for holding a gs_depth_bitmap and the corresponding depth and
  311.  *  colorspace information.
  312.  *
  313.  *  The free_proc pointer is needed to hold the original value of the pattern
  314.  *  instance free structure. This pointer in the pattern instance will be
  315.  *  overwritten with free_pixmap_pattern, which will free the pixmap info
  316.  *  structure when it is freed.
  317.  */
  318. typedef struct pixmap_info_s {
  319.     gs_depth_bitmap bitmap;    /* must be first */
  320.     const gs_color_space *pcspace;
  321.     uint white_index;
  322.     void (*free_proc)(P3(gs_memory_t *, void *, client_name_t));
  323. } pixmap_info;
  324.  
  325. gs_private_st_suffix_add1(st_pixmap_info,
  326.               pixmap_info,
  327.               "pixmap info. struct",
  328.               pixmap_enum_ptr,
  329.               pixmap_reloc_ptr,
  330.               st_gs_depth_bitmap,
  331.               pcspace
  332. );
  333.  
  334. #define st_pixmap_info_max_ptrs (1 + st_tile_bitmap_max_ptrs)
  335.  
  336. /*
  337.  *  Free routine for pattern instances created from pixmaps. This overwrites
  338.  *  the free procedure originally stored in the pattern instance, and stores
  339.  *  the pointer to that procedure in the pixmap_info structure. This procedure
  340.  *  will call the original procedure, then free the pixmap_info structure. 
  341.  *
  342.  *  Note that this routine does NOT release the data in the original pixmap;
  343.  *  that remains the responsibility of the client.
  344.  */
  345. private void
  346. free_pixmap_pattern(
  347.     gs_memory_t *           pmem,
  348.     void *                  pvpinst,
  349.     client_name_t           cname
  350. )
  351. {
  352.     gs_pattern1_instance_t *pinst = (gs_pattern1_instance_t *)pvpinst;
  353.     pixmap_info *ppmap = pinst->template.client_data;
  354.  
  355.     ppmap->free_proc(pmem, pvpinst, cname);
  356.     gs_free_object(pmem, ppmap, cname);
  357. }
  358.  
  359. /*
  360.  *  PaintProcs for bitmap and pixmap patterns.
  361.  */
  362. private int bitmap_paint(P4(gs_image_enum * pen, gs_data_image_t * pim,
  363.               const gs_depth_bitmap * pbitmap, gs_state * pgs));
  364. private int
  365. mask_PaintProc(const gs_client_color * pcolor, gs_state * pgs)
  366. {
  367.     const pixmap_info *ppmap = gs_getpattern(pcolor)->client_data;
  368.     const gs_depth_bitmap *pbitmap = &(ppmap->bitmap);
  369.     gs_image_enum *pen =
  370.     gs_image_enum_alloc(gs_state_memory(pgs), "mask_PaintProc");
  371.     gs_image1_t mask;
  372.  
  373.     if (pen == 0)
  374.     return_error(gs_error_VMerror);
  375.     gs_image_t_init_mask(&mask, true);
  376.     mask.Width = pbitmap->size.x;
  377.     mask.Height = pbitmap->size.y;
  378.     gs_image_init(pen, &mask, false, pgs);
  379.     return bitmap_paint(pen, (gs_data_image_t *) & mask, pbitmap, pgs);
  380. }
  381. private int
  382. image_PaintProc(const gs_client_color * pcolor, gs_state * pgs)
  383. {
  384.     const pixmap_info *ppmap = gs_getpattern(pcolor)->client_data;
  385.     const gs_depth_bitmap *pbitmap = &(ppmap->bitmap);
  386.     gs_image_enum *pen =
  387.     gs_image_enum_alloc(gs_state_memory(pgs), "image_PaintProc");
  388.     const gs_color_space *pcspace =
  389.     (ppmap->pcspace == 0 ?
  390.      gs_cspace_DeviceGray((const gs_imager_state *)pgs) :
  391.      ppmap->pcspace);
  392.     gx_image_enum_common_t *pie;
  393.     gs_image4_t image;
  394.     int code;
  395.  
  396.     if (pen == 0)
  397.     return_error(gs_error_VMerror);
  398.     gs_image4_t_init(&image, pcspace);
  399.     image.Width = pbitmap->size.x;
  400.     image.Height = pbitmap->size.y;
  401.     image.MaskColor_is_range = false;
  402.     image.MaskColor[0] = ppmap->white_index;
  403.     image.Decode[0] = 0;
  404.     image.Decode[1] = (1 << pbitmap->pix_depth) - 1;
  405.     image.BitsPerComponent = pbitmap->pix_depth;
  406.     /* backwards compatibility */
  407.     if (ppmap->pcspace == 0) {
  408.     image.Decode[0] = 1.0;
  409.     image.Decode[1] = 0.0;
  410.     }
  411.     code = gs_image_begin_typed((const gs_image_common_t *)&image, pgs,
  412.                 false, &pie);
  413.     if (code < 0)
  414.     return code;
  415.     code = gs_image_enum_init(pen, pie, (gs_data_image_t *)&image, pgs);
  416.     if (code < 0)
  417.     return code;
  418.     return bitmap_paint(pen, (gs_data_image_t *) & image, pbitmap, pgs);
  419. }
  420. /* Finish painting any kind of bitmap pattern. */
  421. private int
  422. bitmap_paint(gs_image_enum * pen, gs_data_image_t * pim,
  423.          const gs_depth_bitmap * pbitmap, gs_state * pgs)
  424. {
  425.     uint raster = pbitmap->raster;
  426.     uint nbytes = (pim->Width * pbitmap->pix_depth + 7) >> 3;
  427.     uint used;
  428.     const byte *dp = pbitmap->data;
  429.     int n;
  430.     int code = 0;
  431.  
  432.     if (nbytes == raster)
  433.     code = gs_image_next(pen, dp, nbytes * pim->Height, &used);
  434.     else
  435.     for (n = pim->Height; n > 0 && code >= 0; dp += raster, --n)
  436.         code = gs_image_next(pen, dp, nbytes, &used);
  437.     gs_image_cleanup(pen);
  438.     gs_free_object(gs_state_memory(pgs), pen, "bitmap_paint");
  439.     return code;
  440. }
  441.  
  442. /*
  443.  * Make a pattern from a bitmap or pixmap. The pattern may be colored or
  444.  * uncolored, as determined by the mask operand. This code is intended
  445.  * primarily for use by PCL.
  446.  *
  447.  * See the comment prior to the declaration of this function in gscolor2.h
  448.  * for further information.
  449.  */
  450. int
  451. gs_makepixmappattern(
  452.             gs_client_color * pcc,
  453.             const gs_depth_bitmap * pbitmap,
  454.             bool mask,
  455.             const gs_matrix * pmat,
  456.             long id,
  457.             const gs_color_space * pcspace,
  458.             uint white_index,
  459.             gs_state * pgs,
  460.             gs_memory_t * mem
  461. )
  462. {
  463.  
  464.     gs_pattern1_template_t pat;
  465.     pixmap_info *ppmap;
  466.     gs_matrix mat, smat;
  467.     int code;
  468.  
  469.     /* check that the data is legitimate */
  470.     if ((mask) || (pcspace == 0)) {
  471.     if (pbitmap->pix_depth != 1)
  472.         return_error(gs_error_rangecheck);
  473.     pcspace = 0;
  474.     } else if (gs_color_space_get_index(pcspace) != gs_color_space_index_Indexed)
  475.     return_error(gs_error_rangecheck);
  476.     if (pbitmap->num_comps != 1)
  477.     return_error(gs_error_rangecheck);
  478.  
  479.     /* allocate and initialize a pixmap_info structure for the paint proc */
  480.     if (mem == 0)
  481.     mem = gs_state_memory(pgs);
  482.     ppmap = gs_alloc_struct(mem,
  483.                 pixmap_info,
  484.                 &st_pixmap_info,
  485.                 "makepximappattern"
  486.     );
  487.     if (ppmap == 0)
  488.     return_error(gs_error_VMerror);
  489.     ppmap->bitmap = *pbitmap;
  490.     ppmap->pcspace = pcspace;
  491.     ppmap->white_index = white_index;
  492.  
  493.     /* set up the client pattern structure */
  494.     gs_pattern1_init(&pat);
  495.     uid_set_UniqueID(&pat.uid, (id == no_UniqueID) ? gs_next_ids(1) : id);
  496.     pat.PaintType = (mask ? 2 : 1);
  497.     pat.TilingType = 1;
  498.     pat.BBox.p.x = 0;
  499.     pat.BBox.p.y = 0;
  500.     pat.BBox.q.x = pbitmap->size.x;
  501.     pat.BBox.q.y = pbitmap->size.y;
  502.     pat.XStep = pbitmap->size.x;
  503.     pat.YStep = pbitmap->size.y;
  504.     pat.PaintProc = (mask ? mask_PaintProc : image_PaintProc);
  505.     pat.client_data = ppmap;
  506.  
  507.     /* set the ctm to be the identity */
  508.     gs_currentmatrix(pgs, &smat);
  509.     gs_make_identity(&mat);
  510.     gs_setmatrix(pgs, &mat);
  511.  
  512.     /* build the pattern, restore the previous matrix */
  513.     if (pmat == NULL)
  514.     pmat = &mat;
  515.     if ((code = gs_makepattern(pcc, &pat, pmat, pgs, mem)) != 0)
  516.     gs_free_object(mem, ppmap, "makebitmappattern_xform");
  517.     else {
  518.     /*
  519.      * If this is not a masked pattern and if the white pixel index
  520.      * is outside of the representable range, we don't need to go to
  521.      * the trouble of accumulating a mask that will just be all 1s.
  522.      */
  523.     gs_pattern1_instance_t *pinst =
  524.         (gs_pattern1_instance_t *)pcc->pattern;
  525.  
  526.     if (!mask && (white_index >= (1 << pbitmap->pix_depth)))
  527.         pinst->uses_mask = false;
  528.  
  529.         /* overwrite the free procedure for the pattern instance */
  530.         ppmap->free_proc = pinst->rc.free;
  531.         pinst->rc.free = free_pixmap_pattern;
  532.  
  533.     /*
  534.      * Since the PaintProcs don't reference the saved color space or
  535.      * color, clear these so that there isn't an extra retained
  536.      * reference to the Pattern object.
  537.      */
  538.     gs_setgray(pinst->saved, 0.0);
  539.  
  540.     }
  541.     gs_setmatrix(pgs, &smat);
  542.     return code;
  543. }
  544.  
  545. /*
  546.  *  Backwards compatibility.
  547.  */
  548. int
  549. gs_makebitmappattern_xform(
  550.                   gs_client_color * pcc,
  551.                   const gx_tile_bitmap * ptile,
  552.                   bool mask,
  553.                   const gs_matrix * pmat,
  554.                   long id,
  555.                   gs_state * pgs,
  556.                   gs_memory_t * mem
  557. )
  558. {
  559.     gs_depth_bitmap bitmap;
  560.  
  561.     /* build the bitmap the size of one repetition */
  562.     bitmap.data = ptile->data;
  563.     bitmap.raster = ptile->raster;
  564.     bitmap.size.x = ptile->rep_width;
  565.     bitmap.size.y = ptile->rep_height;
  566.     bitmap.id = ptile->id;    /* shouldn't matter */
  567.     bitmap.pix_depth = 1;
  568.     bitmap.num_comps = 1;
  569.  
  570.     return gs_makepixmappattern(pcc, &bitmap, mask, pmat, id, 0, 0, pgs, mem);
  571. }
  572.  
  573.  
  574. /* ------ Color space implementation ------ */
  575.  
  576. /*
  577.  * Defined the Pattern device color types.  We need a masked analogue of
  578.  * each of the non-pattern types, to handle uncolored patterns.  We use
  579.  * 'masked_fill_rect' instead of 'masked_fill_rectangle' in order to limit
  580.  * identifier lengths to 32 characters.
  581.  */
  582. private dev_color_proc_load(gx_dc_pattern_load);
  583. /*dev_color_proc_fill_rectangle(gx_dc_pattern_fill_rectangle); *//*gxp1fill.h */
  584. private dev_color_proc_equal(gx_dc_pattern_equal);
  585. private dev_color_proc_load(gx_dc_pure_masked_load);
  586.  
  587. /*dev_color_proc_fill_rectangle(gx_dc_pure_masked_fill_rect); *//*gxp1fill.h */
  588. private dev_color_proc_equal(gx_dc_pure_masked_equal);
  589. private dev_color_proc_load(gx_dc_binary_masked_load);
  590.  
  591. /*dev_color_proc_fill_rectangle(gx_dc_binary_masked_fill_rect); *//*gxp1fill.h */
  592. private dev_color_proc_equal(gx_dc_binary_masked_equal);
  593. private dev_color_proc_load(gx_dc_colored_masked_load);
  594.  
  595. /*dev_color_proc_fill_rectangle(gx_dc_colored_masked_fill_rect); *//*gxp1fill.h */
  596. private dev_color_proc_equal(gx_dc_colored_masked_equal);
  597.  
  598. /* The device color types are exported for gxpcmap.c. */
  599. gs_private_st_composite(st_dc_pattern, gx_device_color, "dc_pattern",
  600.             dc_pattern_enum_ptrs, dc_pattern_reloc_ptrs);
  601. const gx_device_color_type_t gx_dc_pattern = {
  602.     &st_dc_pattern,
  603.     gx_dc_pattern_load, gx_dc_pattern_fill_rectangle,
  604.     gx_dc_default_fill_masked, gx_dc_pattern_equal
  605. };
  606.  
  607. extern_st(st_dc_ht_binary);
  608. gs_private_st_composite(st_dc_pure_masked, gx_device_color, "dc_pure_masked",
  609.             dc_masked_enum_ptrs, dc_masked_reloc_ptrs);
  610. const gx_device_color_type_t gx_dc_pure_masked = {
  611.     &st_dc_pure_masked,
  612.     gx_dc_pure_masked_load, gx_dc_pure_masked_fill_rect,
  613.     gx_dc_default_fill_masked, gx_dc_pure_masked_equal
  614. };
  615.  
  616. gs_private_st_composite(st_dc_binary_masked, gx_device_color,
  617.             "dc_binary_masked", dc_binary_masked_enum_ptrs,
  618.             dc_binary_masked_reloc_ptrs);
  619. const gx_device_color_type_t gx_dc_binary_masked = {
  620.     &st_dc_binary_masked,
  621.     gx_dc_binary_masked_load, gx_dc_binary_masked_fill_rect,
  622.     gx_dc_default_fill_masked, gx_dc_binary_masked_equal
  623. };
  624.  
  625. gs_private_st_composite_only(st_dc_colored_masked, gx_device_color,
  626.                  "dc_colored_masked",
  627.                  dc_masked_enum_ptrs, dc_masked_reloc_ptrs);
  628. const gx_device_color_type_t gx_dc_colored_masked = {
  629.     &st_dc_colored_masked,
  630.     gx_dc_colored_masked_load, gx_dc_colored_masked_fill_rect,
  631.     gx_dc_default_fill_masked, gx_dc_colored_masked_equal
  632. };
  633.  
  634. #undef gx_dc_type_pattern
  635. const gx_device_color_type_t *const gx_dc_type_pattern = &gx_dc_pattern;
  636. #define gx_dc_type_pattern (&gx_dc_pattern)
  637.  
  638. /* GC procedures */
  639. private 
  640. ENUM_PTRS_WITH(dc_pattern_enum_ptrs, gx_device_color *cptr)
  641. {
  642.     return ENUM_USING(st_dc_pure_masked, vptr, size, index - 1);
  643. }
  644. case 0:
  645. {
  646.     gx_color_tile *tile = cptr->colors.pattern.p_tile;
  647.  
  648.     ENUM_RETURN((tile == 0 ? tile : tile - tile->index));
  649. }
  650. ENUM_PTRS_END
  651. private RELOC_PTRS_WITH(dc_pattern_reloc_ptrs, gx_device_color *cptr)
  652. {
  653.     gx_color_tile *tile = cptr->colors.pattern.p_tile;
  654.  
  655.     if (tile != 0) {
  656.     uint index = tile->index;
  657.  
  658.     RELOC_TYPED_OFFSET_PTR(gx_device_color, colors.pattern.p_tile, index);
  659.     }
  660.     RELOC_USING(st_dc_pure_masked, vptr, size);
  661. }
  662. RELOC_PTRS_END
  663. private ENUM_PTRS_WITH(dc_masked_enum_ptrs, gx_device_color *cptr)
  664. ENUM_SUPER(gx_device_color, st_client_color, ccolor, 1);
  665. case 0:
  666. {
  667.     gx_color_tile *mask = cptr->mask.m_tile;
  668.  
  669.     ENUM_RETURN((mask == 0 ? mask : mask - mask->index));
  670. }
  671. ENUM_PTRS_END
  672. private RELOC_PTRS_WITH(dc_masked_reloc_ptrs, gx_device_color *cptr)
  673. {
  674.     gx_color_tile *mask = cptr->mask.m_tile;
  675.  
  676.     RELOC_SUPER(gx_device_color, st_client_color, ccolor);
  677.     if (mask != 0) {
  678.     uint index = mask->index;
  679.  
  680.     RELOC_TYPED_OFFSET_PTR(gx_device_color, mask.m_tile, index);
  681.     }
  682. }
  683. RELOC_PTRS_END
  684. private ENUM_PTRS_BEGIN(dc_binary_masked_enum_ptrs)
  685. {
  686.     return ENUM_USING(st_dc_ht_binary, vptr, size, index - 2);
  687. }
  688. case 0:
  689. case 1:
  690. return ENUM_USING(st_dc_pure_masked, vptr, size, index);
  691. ENUM_PTRS_END
  692. private RELOC_PTRS_BEGIN(dc_binary_masked_reloc_ptrs)
  693. {
  694.     RELOC_USING(st_dc_pure_masked, vptr, size);
  695.     RELOC_USING(st_dc_ht_binary, vptr, size);
  696. }
  697. RELOC_PTRS_END
  698.  
  699. /* Macros for pattern loading */
  700. #define FINISH_PATTERN_LOAD\
  701.     while ( !gx_pattern_cache_lookup(pdevc, pis, dev, select) )\
  702.      { code = gx_pattern_load(pdevc, pis, dev, select);\
  703.        if ( code < 0 ) break;\
  704.      }\
  705.     return code;
  706.  
  707. /* Ensure that a colored Pattern is loaded in the cache. */
  708. private int
  709. gx_dc_pattern_load(gx_device_color * pdevc, const gs_imager_state * pis,
  710.            gx_device * dev, gs_color_select_t select)
  711. {
  712.     int code = 0;
  713.  
  714.     FINISH_PATTERN_LOAD
  715. }
  716. /* Ensure that an uncolored Pattern is loaded in the cache. */
  717. private int
  718. gx_dc_pure_masked_load(gx_device_color * pdevc, const gs_imager_state * pis,
  719.                gx_device * dev, gs_color_select_t select)
  720. {
  721.     int code = (*gx_dc_type_data_pure.load) (pdevc, pis, dev, select);
  722.  
  723.     if (code < 0)
  724.     return code;
  725.     FINISH_PATTERN_LOAD
  726. }
  727. private int
  728. gx_dc_binary_masked_load(gx_device_color * pdevc, const gs_imager_state * pis,
  729.              gx_device * dev, gs_color_select_t select)
  730. {
  731.     int code = (*gx_dc_type_data_ht_binary.load) (pdevc, pis, dev, select);
  732.  
  733.     if (code < 0)
  734.     return code;
  735.     FINISH_PATTERN_LOAD
  736. }
  737. private int
  738. gx_dc_colored_masked_load(gx_device_color * pdevc, const gs_imager_state * pis,
  739.               gx_device * dev, gs_color_select_t select)
  740. {
  741.     int code = (*gx_dc_type_data_ht_colored.load) (pdevc, pis, dev, select);
  742.  
  743.     if (code < 0)
  744.     return code;
  745.     FINISH_PATTERN_LOAD
  746. }
  747.  
  748. /* Look up a pattern color in the cache. */
  749. bool
  750. gx_pattern_cache_lookup(gx_device_color * pdevc, const gs_imager_state * pis,
  751.             gx_device * dev, gs_color_select_t select)
  752. {
  753.     gx_pattern_cache *pcache = pis->pattern_cache;
  754.     gx_bitmap_id id = pdevc->mask.id;
  755.  
  756.     if (id == gx_no_bitmap_id) {
  757.     color_set_null_pattern(pdevc);
  758.     return true;
  759.     }
  760.     if (pcache != 0) {
  761.     gx_color_tile *ctile = &pcache->tiles[id % pcache->num_tiles];
  762.  
  763.     if (ctile->id == id &&
  764.         (pdevc->type != &gx_dc_pattern ||
  765.          ctile->depth == dev->color_info.depth)
  766.         ) {
  767.         int px = pis->screen_phase[select].x;
  768.         int py = pis->screen_phase[select].y;
  769.  
  770.         if (pdevc->type == &gx_dc_pattern) {    /* colored */
  771.         pdevc->colors.pattern.p_tile = ctile;
  772.         color_set_phase_mod(pdevc, px, py,
  773.                     ctile->tbits.rep_width,
  774.                     ctile->tbits.rep_height);
  775.         }
  776.         pdevc->mask.m_tile =
  777.         (ctile->tmask.data == 0 ? (gx_color_tile *) 0 :
  778.          ctile);
  779.         pdevc->mask.m_phase.x = -px;
  780.         pdevc->mask.m_phase.y = -py;
  781.         return true;
  782.     }
  783.     }
  784.     return false;
  785. }
  786.  
  787. #undef FINISH_PATTERN_LOAD
  788.  
  789. /* Compare two Pattern colors for equality. */
  790. private bool
  791. gx_dc_pattern_equal(const gx_device_color * pdevc1,
  792.             const gx_device_color * pdevc2)
  793. {
  794.     return pdevc2->type == pdevc1->type &&
  795.     pdevc1->phase.x == pdevc2->phase.x &&
  796.     pdevc1->phase.y == pdevc2->phase.y &&
  797.     pdevc1->mask.id == pdevc2->mask.id;
  798. }
  799. private bool
  800. gx_dc_pure_masked_equal(const gx_device_color * pdevc1,
  801.             const gx_device_color * pdevc2)
  802. {
  803.     return (*gx_dc_type_pure->equal) (pdevc1, pdevc2) &&
  804.     pdevc1->mask.id == pdevc2->mask.id;
  805. }
  806. private bool
  807. gx_dc_binary_masked_equal(const gx_device_color * pdevc1,
  808.               const gx_device_color * pdevc2)
  809. {
  810.     return (*gx_dc_type_ht_binary->equal) (pdevc1, pdevc2) &&
  811.     pdevc1->mask.id == pdevc2->mask.id;
  812. }
  813. private bool
  814. gx_dc_colored_masked_equal(const gx_device_color * pdevc1,
  815.                const gx_device_color * pdevc2)
  816. {
  817.     return (*gx_dc_type_ht_colored->equal) (pdevc1, pdevc2) &&
  818.     pdevc1->mask.id == pdevc2->mask.id;
  819. }
  820.